#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <wait.h>

#define NUM 10

typedef void (*task)(void);
task task_queue[NUM];

void init_task()
{
    for (int i = 0; i < NUM; ++i)
        task_queue[i] = NULL;
}

int add_task(task t)
{
    int pos = 0;
    while (pos < NUM)
    {
        if (task_queue[pos] == NULL)
            break;
        ++pos;
    }
    if (pos < NUM)
    {   
        task_queue[pos] = t;
        return pos;
    }
    else
        return -1;
}

void execute_task()
{
    for (int i = 0; i < NUM; ++i)
    {
        if (task_queue[i] != NULL)
        {
            task_queue[i]();
            sleep(1);
        }
    }
}

void task1()
{
    printf("绘制界面 pid = %d\n", getpid());
}

void task2()
{
    printf("检查环境 pid = %d\n", getpid());
}

void task3()
{
    printf("等待响应 pid: %d\n", getpid());
}

int main()
{
    pid_t id = fork();

    if (id == 0)
    {
        for (int i = 0; i < 5; ++i)
        {
            printf("子进程: pid: %d ppid: %d\n", getpid(), getppid());
            sleep(2);
        }
        printf("子进程exit\n");
        exit(0);
    }
    else if (id > 0)
    {
        printf("父进程: pid: %d ppid: %d\n", getpid(), getppid());
        
        init_task();
        add_task(task1);
        add_task(task2);
        add_task(task3);
        
        while (1)
        {
            int stat = 0;
            pid_t ret = waitpid(id, &stat, WNOHANG);
            if (ret > 0)
            {
                if (WIFEXITED(stat))
                    printf("正常退出 exit code = %d\n", WEXITSTATUS(stat));
                else
                    printf("异常退出 exit code = %d exit sig = %d\n", WEXITSTATUS(stat), stat & 0x7F);
                break;
            }
            else if (ret == 0)
            {
                execute_task();
            }
            else
            {
                printf("wait error\n");
                break;
            }
        }
    }
    else
        printf("fork error\n");

    return 0;
}
